﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ufida.u9.ait.openapi.utils
{
    /// <summary>
    /// JSON工具类
    /// </summary>
    public class JSONUtils
    {
        /// <summary>
        /// 将Token转换成字符串列表
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static List<string> toListString(JToken token)
        {
            if (token == null)
                return new List<string>();

            // 如果是 JArray，尝试转换每个元素为字符串
            if (token is JArray array)
            {
                return array
                    .Select(item => item?.ToString())
                    .Where(s => s != null) // 可选：过滤 null
                    .ToList();
            }

            // 如果是单个值（如字符串、数字等），包装成单元素列表
            if (token.Type != JTokenType.Null)
            {
                return new List<string> { token.ToString() };
            }

            return new List<string>();
        }

        /// <summary>
        /// 将 JArray 转换为 List<Dictionary<string, object>>
        /// </summary>
        /// <param name="jArray">要转换的 JArray</param>
        /// <returns>转换后的列表，若输入为 null 或元素非 JObject 则跳过或返回空列表</returns>
        public static List<Dictionary<string, object>> toList(JArray jArray)
        {
            var result = new List<Dictionary<string, object>>();

            if (jArray == null)
                return result;

            foreach (var token in jArray)
            {
                if (token is JObject jObject)
                {
                    // 使用 ToObject 自动转换为 Dictionary<string, object>
                    var dict = jObject.ToObject<Dictionary<string, object>>();
                    result.Add(dict ?? new Dictionary<string, object>());
                }
                // 如果不是 JObject（比如是字符串、数字等），则跳过
            }

            return result;
        }

        /// <summary>
        /// 将 List<Dictionary<string, object>> 转换为 JArray
        /// </summary>
        /// <param name="list">要转换的数据列表</param>
        /// <returns>转换后的 JArray，若输入为 null 则返回空 JArray</returns>
        public static JArray toJArray(List<Dictionary<string, object>> list)
        {
            if (list == null)
                return new JArray();

            var jArray = new JArray();

            foreach (var dict in list)
            {
                var jObject = new JObject();
                if (dict != null)
                {
                    foreach (var kvp in dict)
                    {
                        // 自动处理 null 和任意 object 类型
                        jObject[kvp.Key] = JToken.FromObject(kvp.Value);
                    }
                }
                jArray.Add(jObject);
            }

            return jArray;
        }

        /// <summary>
        /// 获取 JObject 的所有属性名称（键名）
        /// </summary>
        /// <param name="jObject">要处理的 JObject</param>
        /// <returns>包含所有属性名称的 List<string>，若输入为 null 则返回空列表</returns>
        public static List<string> getPropertyNames(JObject jObject)
        {
            if (jObject == null)
                return new List<string>();

            return jObject.Properties().Select(p => p.Name).ToList();
        }

        /// <summary>
        /// 将 DataTable 转换为 JArray
        /// </summary>
        /// <param name="ds">要转换的 ds</param>
        /// <returns>转换后的 JArray，若输入为 null 或空表则返回空 JArray</returns>
        public static JArray dsToJArray(DataSet ds)
        {
            if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
                return new JArray();

            var jArray = new JArray();

            foreach (DataRow row in ds.Tables[0].Rows)
            {
                var jObject = new JObject();
                foreach (DataColumn col in ds.Tables[0].Columns)
                {
                    object value = row[col];
                    // 处理 DBNull -> null
                    jObject[col.ColumnName] = JToken.FromObject(value == DBNull.Value ? null : value);
                }
                jArray.Add(jObject);
            }

            return jArray;
        }

        /// <summary>
        /// 根据点号分隔的路径（如 "AA.BB"）从 JObject 中获取 JToken。
        /// 路径中每一级必须是 JObject，且键存在。
        /// </summary>
        /// <param name="json">源 JObject</param>
        /// <param name="path">点号分隔的路径，如 "User.Profile"</param>
        /// <returns>找到的 JToken，否则 null</returns>
        public static JToken getJToken(JObject json, string path)
        {
            if (json == null || string.IsNullOrEmpty(path))
                return null;

            string[] parts = path.Split('.');
            JToken current = json;

            foreach (string part in parts)
            {
                if (current is JObject obj && obj.TryGetValue(part, out JToken next))
                {
                    current = next;
                }
                else
                {
                    // 路径中断：当前不是 JObject，或 key 不存在
                    return null;
                }
            }

            return current; // 可能是 JValue, JObject, JArray 等
        }

        /// <summary>
        /// 获取JSON对象的子对象,如果没有，则返回null
        /// </summary>
        /// <param name="json">JSON对象</param>
        /// <param name="key">子对象Key,支持"AA.BB"递归访问孙对象</param>
        /// <returns></returns>
        public static JObject getJObject(JObject json, string key)
        {
            if (json == null || string.IsNullOrEmpty(key))
                return null;

            // 拆分路径，例如 "AA.BB.CC" -> ["AA", "BB", "CC"]
            string[] parts = key.Split('.');

            JToken current = json;
            foreach (string part in parts)
            {
                if (current is JObject obj && obj.TryGetValue(part, out JToken next))
                {
                    // 如果不是最后一级，必须是 JObject 才能继续深入
                    if (next?.Type == JTokenType.Null)
                        return null;

                    current = next;
                }
                else
                {
                    // 路径中断：key 不存在或当前不是 JObject
                    return null;
                }
            }

            // 最终结果必须是 JObject
            return current as JObject;
        }
        /// <summary>
        /// 获取JSON对象的XX属性的string值
        /// </summary>
        /// <param name="json">json对象</param>
        /// <param name="key">对象属性</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static string getString(JToken json, string key, string defaultValue = "")
        {
            if (json == null || string.IsNullOrEmpty(key))
                return defaultValue;

            var token = json[key];
            if (token == null || token.Type == JTokenType.Null)
                return defaultValue;

            if (token.Type == JTokenType.String)
                return token.Value<string>();

            // 只处理基本标量类型，避免 JObject/JArray 被 ToString()
            switch (token.Type)
            {
                case JTokenType.String:
                case JTokenType.Integer:
                case JTokenType.Float:
                case JTokenType.Boolean:
                case JTokenType.Date:
                case JTokenType.Guid:
                case JTokenType.Uri:
                case JTokenType.TimeSpan:
                    return token.ToString(); // 安全转换为字符串表示

                default:
                    return defaultValue; // 不处理对象、数组、未定义等类型
            }
        }

        /// <summary>
        /// 获取JSON对象的XX属性的int值
        /// </summary>
        /// <param name="json">json对象</param>
        /// <param name="key">对象属性</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static int getInt(JToken json, string key, int defaultValue = 0)
        {
            if (json == null || string.IsNullOrEmpty(key))
                return defaultValue;

            var token = json[key];
            if (token == null || token.Type == JTokenType.Null)
                return defaultValue;

            try
            {
                return token.Value<int>();
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 对象->JSON字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static String toJSONStr(Object obj)
        {
            return JsonConvert.SerializeObject(obj,
                Formatting.None,//格式化
                new JsonSerializerSettings //序列化设置
                {
                    NullValueHandling = NullValueHandling.Ignore,//去掉空值
                    DefaultValueHandling = DefaultValueHandling.Ignore,//去掉默认值
                });
        }
        /// <summary>
        /// JSON字符串->具体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonstr"></param>
        /// <returns></returns>
        public static T toObject<T>(String jsonstr)
        {
            return JsonConvert.DeserializeObject<T>(jsonstr);
        }
        /// <summary>
        /// JSON字符串->Map
        /// </summary>
        /// <param name="jsonstr"></param>
        /// <returns></returns>
        public static Dictionary<String,Object> toMap(String jsonstr)
        {
            return JsonConvert.DeserializeObject<Dictionary<String, Object>>(jsonstr);
        }
        /// <summary>
        /// JSON字符串->MapList
        /// </summary>
        /// <param name="jsonstr"></param>
        /// <returns></returns>
        public static List<Dictionary<String,Object>> toMapList(String jsonstr)
        {
            return toObject<List<Dictionary<String,Object>>>(jsonstr);
        }
        /// <summary>
        /// JSON字符串->JSON对象
        /// </summary>
        /// <param name="jsonstr"></param>
        /// <returns></returns>
        public static object toJSONObject(String jsonstr)
        {
            //DeserializeObject 返回JObject或JArray
            //JObject访问具体属性,json["arr"],返回JToken
            //JToken的具体类型可以是基础类型或JObject/JArray

            /**
             * 举例说明
             * 
            using Newtonsoft.Json.Linq;

            string jsonString = @"{
    ""name"": ""Alice"",
    ""age"": 30,
    ""isStudent"": false,
    ""address"": {
        ""city"": ""Beijing"",
        ""zipcode"": ""100000""
    },
    ""hobbies"": [""reading"", ""swimming""]
}";

            JObject jObject = JObject.Parse(jsonString);

            // 访问基本属性 (需要 .Value<T>() 或强转)
            string name = jObject["name"]?.Value<string>(); // 注意：?. 防止属性不存在返回 null
            int age = jObject["age"]?.Value<int>() ?? 0;
            bool isStudent = jObject["isStudent"]?.Value<bool>() ?? false;

            // 访问嵌套的 JObject
            JObject address = jObject["address"] as JObject;
            if (address != null)
            {
                string city = address["city"]?.Value<string>();
                string zipcode = address["zipcode"]?.Value<string>();
            }

            // 访问 JArray
            JArray hobbies = jObject["hobbies"] as JArray;
            if (hobbies != null)
            {
                foreach (JToken hobby in hobbies)
                {
                    Console.WriteLine(hobby.Value<string>());
                }
                // 或者直接转换为 List<string>
                // List<string> hobbyList = hobbies.ToObject<List<string>>();
            }
            */

            object json = JsonConvert.DeserializeObject(jsonstr);
            return json;
        }
        /// <summary>
        /// 读取JSON文件
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns>JSON对象</returns>
        public static JObject readJSONFile(String path)
        {
            string content = FileUtils.ReadTxtFile(path);
            //DeserializeObject 返回JObject或JArray
            //JObject访问具体属性,json["arr"],返回JToken
            //JToken的具体类型可以是基础类型或JObject/JArray
            JObject json = (JObject)JsonConvert.DeserializeObject(content);
            return json;
        }

        /// <summary>
        /// 读取JSON文件,并转换为指定类型
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns>指定类型对象</returns>
        public static T readJSONFile<T>(String path)
        {
            string content = FileUtils.ReadTxtFile(path);
            T obj = JsonConvert.DeserializeObject<T>(content);
            return obj;
        }
    }
}
